/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.miage.pki.tools;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.RSAPublicKey;
import java.util.ArrayList;
import java.util.Date;
import java.util.Random;
import javax.security.auth.x500.X500Principal;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.x509.X509V1CertificateGenerator;

import com.miage.pki.service.PKIServiceImpl;

import sun.misc.BASE64Encoder;

/**
 *
 * @author Gaetan
 */
public class SSLCertificateTools {

    public X509Certificate generateCertificate(Date startDate, Date expiryDate, KeyPair keyPair, KeyUsage keyUsage, String subjectDN) {

        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

        //Certificat top level
        X509Certificate certifTopLevel = KeyStoreTools.getCertificateTopLevel();
        PrivateKey privateKeyTopLevel = KeyStoreTools.getPrivateKeyTopLevel();
        
        
        //Certificat généré
        X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
        X500Principal subjectName = new X500Principal(subjectDN);

        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();
        
        certGen.setSerialNumber(new BigInteger(64, new Random(System.currentTimeMillis())));
        certGen.setIssuerDN(certifTopLevel.getSubjectX500Principal());
        certGen.setNotBefore(startDate);
        certGen.setNotAfter(expiryDate);
        certGen.setSubjectDN(subjectName);
        certGen.setPublicKey(publicKey);

        if (publicKey instanceof RSAPublicKey) {
            certGen.setSignatureAlgorithm("sha1withRSA");
        } else if (publicKey instanceof DSAPublicKey) {
            certGen.setSignatureAlgorithm("sha1withDSA");
        }

        X509Certificate cert = null;
        try {
            //certGen.addExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(true));
            //certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(certifTopLevel));
            //certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(publicKey));
            //cert = certGen.generate(privateKeyTopLevel, "BC");
        } catch (Exception ex) {
        }

        return cert;
    }    
    
    public boolean saveX509Certificate(X509Certificate cert, String fileName) {
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(new File(PKIServiceImpl.certificatePath+fileName+".cer"));
            out.write("-----BEGIN CERTIFICATE-----\n".getBytes());
            out.write(new BASE64Encoder().encode(cert.getEncoded()).getBytes());
            out.write("\n-----END CERTIFICATE-----\n".getBytes());
            out.close();
        } catch (Exception ex) {
            return false;
        }
        return true;
    }
    
    public void savePKCS12Certificate(KeyStore ks, String fileName, String password) throws Exception{
        FileOutputStream out = new FileOutputStream(PKIServiceImpl.certificatePath+fileName+".p12");
        ks.store(out, password.toCharArray());
    }

    public static String getInfoCertificate(X509Certificate cert) {

        StringBuilder str = new StringBuilder("Détenteur : ");
        X500Principal subject = cert.getSubjectX500Principal();
        str.append(subject.getName());

        str.append("\nAutorité de certification : ");
        X500Principal issuer = cert.getIssuerX500Principal();
        str.append(issuer.getName());

        str.append("\nValable du ");
        str.append(cert.getNotBefore());

        str.append("\nValable jusqu'au ");
        str.append(cert.getNotAfter());

        str.append("\n");
        str.append(KeyTools.getInfoPublicKey(cert.getPublicKey()));

        return str.toString();
    }

    public ArrayList<Certificate> loadCertificateFile(String fileName) {
        ArrayList<Certificate> arrCertif = new ArrayList<Certificate>();
        InputStream in = null;
        try {
            in = new BufferedInputStream(new FileInputStream(new File(fileName)));
            CertificateFactory factory = CertificateFactory.getInstance("X509");
            while (in.available() > 0) {
                arrCertif.add(factory.generateCertificate(in));
            }
            in.close();
        } catch (Exception ex) {
        }
        return arrCertif;
    }
}
